/* 
 * This file part of cget - A libcurl based downloading tool.
 * http://lianwei3.googlepages.com/home2
 * Copyright (C) 2006 Wei Lian <lianwei3@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "header.h"
#include "filemanager.h"
#include "util.h"



void FileManager::file_open(char *outfile, char *outfile_cg,
			    std::vector < struct ThreadInfo >*vec_info)
{
    uint num_block;
    fp = fopen(outfile_cg, "r");
    if (fp) {			///file exist
	struct stat file_stat;
	stat(outfile_cg, &file_stat);
	if (file_stat.st_size == vec_info->at(0).length) {
	    rename(outfile_cg, outfile);
	    exit(0);
	}
	if (file_stat.st_size < vec_info->at(0).length) {
	    fprintf(stderr, "file length is shorter than expected\n");
	    exit(0);
	}
	fseeko(fp, vec_info->at(0).length, SEEK_SET);
	fread(&num_block, sizeof(uint), 1, fp);
	if (file_stat.st_size !=
	    (off_t) (vec_info->at(0).length + sizeof(int) +
		     num_block * 2 * sizeof(off_t))) {
	    fprintf(stderr, "your cg! file is damaged\n");
	    exit(0);
	}
	uint min = min_value(num_block, vec_info->size());
	for (uint i = 0; i < min; i++) {
	    fread(&vec_info->at(i).seek, sizeof(off_t), 1, fp);
	    fread(&vec_info->at(i).end, sizeof(off_t), 1, fp);
	}
	///if vec_thread_info size < num_block
	if (min < num_block)
	    vec_info->reserve(num_block);
	uint org_size = vec_info->size();
	while (min < num_block) {
	    vec_info->push_back(vec_info->at(min % org_size));
	    fread(&vec_info->at(min).seek, sizeof(off_t), 1, fp);
	    fread(&vec_info->at(min).end, sizeof(off_t), 1, fp);
	    min++;
	}
	///if vec_thread_info size > num_block
	while (num_block < vec_info->size()) {
	    reallocate(vec_info, 0, num_block, num_block, -1);
	    num_block++;
	}
	///close 
	fclose(fp);
    } else {			//new file
	for (uint i = 0; i < vec_info->size(); i++) {
	    vec_info->at(i).seek =
		vec_info->at(i).length / vec_info->size() * i;
	    vec_info->at(i).end =
		vec_info->at(i).length / vec_info->size() * (i + 1) - 1;
	    vec_info->at(i).end =
		vec_info->at(i).end > 0 ? vec_info->at(i).end : 0;
	}
	vec_info->at(vec_info->size() - 1).end =
	    vec_info->at(0).length - 1;
    }
    ////store file descriptor and create pipe
    for (uint i = 0; i < vec_info->size(); i++) {
	vec_info->at(i).id = i;
	pipe(vec_info->at(i).pipe);
	assert(vec_info->at(i).seek >= 0);
	if (vec_info->at(i).seek > vec_info->at(i).end) {
	    for (uint j = 0; j < vec_info->size(); j++)
		fprintf(stderr, "err:(%d),seek=%ld,end=%ld,length=%ld",
			j, vec_info->at(j).seek,
			vec_info->at(j).end, vec_info->at(j).length);
	    exit(1);
	}
    }

}
